//
//  UIDevice+Memory.m
//  MexicoLoan
//
//  Created by wxp on 2025/3/1.
//

#import "UIDevice+Memory.h"
#import <sys/sysctl.h>
#import <mach/mach.h>

@implementation UIDevice (Memory)

+ (NSString *)totalDiskSpaceInGB{
    return [NSByteCountFormatter stringFromByteCount:self.totalDiskSpaceInBytes countStyle:NSByteCountFormatterCountStyleDecimal];
}

+ (NSString *)totalDiskSpaceInMB{
    return [self MBFormatter:self.totalDiskSpaceInBytes];
}

+ (NSString *)freeDiskSpaceInGB{
    return [NSByteCountFormatter stringFromByteCount:self.freeDiskSpaceInBytes countStyle:NSByteCountFormatterCountStyleDecimal];
}

+ (NSString *)freeDiskSpaceInMB{
    return [self MBFormatter:self.freeDiskSpaceInBytes];
}

+ (NSString *)usedDiskSpaceInGB{
    return [NSByteCountFormatter stringFromByteCount:self.usedDiskSpaceInBytes countStyle:NSByteCountFormatterCountStyleDecimal];
}

+ (NSString *)usedDiskSpaceInMB{
    return [self MBFormatter:self.usedDiskSpaceInBytes];
}

+ (NSString *)MBFormatter:(long long)byte{
    NSByteCountFormatter * formater = [[NSByteCountFormatter alloc]init];
    formater.allowedUnits = NSByteCountFormatterUseGB;
    formater.countStyle = NSByteCountFormatterCountStyleDecimal;
    formater.includesUnit = false;
    return [formater stringFromByteCount:byte];
}

+ (long)totalDiskSpaceInBytes{
    NSError * error = nil;
    NSDictionary<NSFileAttributeKey, id> * systemAttributes =  [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
    if (error) {
        return 0;
    }
    long long space = [systemAttributes[NSFileSystemSize] longLongValue];
    return space;
}

+ (long)freeDiskSpaceInBytes{
    if (@available(iOS 11.0, *)) {
        [NSURL alloc];
        NSURL * url = [[NSURL alloc]initFileURLWithPath:[NSString stringWithFormat:@"%@",NSHomeDirectory()]];
        NSError * error = nil;
        NSDictionary<NSURLResourceKey, id> * dict = [url resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&error];
        if (error) {
            return 0;
        }
        long long space = [dict[NSURLVolumeAvailableCapacityForImportantUsageKey] longLongValue];
        return space;
    } else {
        NSError * error = nil;
        NSDictionary<NSFileAttributeKey, id> * systemAttributes =  [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
        if (error) {
            return 0;
        }
        long long space = [systemAttributes[NSFileSystemFreeSize] longLongValue];
        return space;
    }
}

+ (long)usedDiskSpaceInBytes{
    return self.totalDiskSpaceInBytes - self.freeDiskSpaceInBytes;
}

+ (long long)inactiveMemoryInBytes {
    // 获取不活动内存
    vm_statistics_data_t vmStats;
    mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
    host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &count);
    return (vmStats.inactive_count * vm_page_size); // 返回不活动内存大小
}

+ (long long)wiredMemoryInBytes {
    // 获取保留内存
    vm_statistics_data_t vmStats;
    mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
    host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &count);
    return (vmStats.wire_count * vm_page_size); // 返回保留内存大小
}

+ (long long)usedMemoryInBytes {
    // 获取已用内存（包括活动内存、不活动内存、保留内存等）
    task_basic_info_data_t info;
    mach_msg_type_number_t size = TASK_BASIC_INFO_COUNT;
    kern_return_t kr = KERN_SUCCESS;
    kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kr != KERN_SUCCESS) {
        return 0;
    }
    return info.resident_size; // 返回已用内存大小
}

// 活动内存
+ (long long)activeMemoryInBytes {
    // 活动内存一般是已用内存的一部分
    return [self usedMemoryInBytes] - [self inactiveMemoryInBytes] - [self wiredMemoryInBytes];
}

+ (long long)freeMemoryInBytes {
    // 获取可用内存
    vm_statistics_data_t vmStats;
    mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
    host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &count);
    return (vmStats.free_count * vm_page_size); // 返回空闲内存大小
}

// 可清理内存
+ (long long)cleanableMemoryInBytes {
    // 可清理内存可以通过空闲内存和不活动内存来估算
    return [self freeMemoryInBytes] + [self inactiveMemoryInBytes];
}

@end
